package com.liuzb.moodiary.view;

import java.util.Random;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewPropertyAnimator;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.liuzb.moodiary.R;

public class KenBurnsView extends FrameLayout
{

    private static final String TAG = "KenBurnsView";

    private final Handler mHandler;
    private int[] mResourceIds;
    private ImageView[] mImageViews;
    private int mActiveImageIndex = -1;

    private final Random random = new Random();
    private int mSwapMs = 10000;
    private int mFadeInOutMs = 1000;

    private float maxScaleFactor = 1.5F;
    private float minScaleFactor = 1.2F;

    private Runnable mSwapImageRunnable = new Runnable()
    {
        @Override
        public void run()
        {
            swapImage();
            mHandler.postDelayed( mSwapImageRunnable, mSwapMs - mFadeInOutMs * 2 );
        }
    };

    public KenBurnsView( Context context )
    {
        this( context, null );
    }

    public KenBurnsView( Context context, AttributeSet attrs )
    {
        this( context, attrs, 0 );
    }

    public KenBurnsView( Context context, AttributeSet attrs, int defStyle )
    {
        super( context, attrs, defStyle );
        mHandler = new Handler();
    }

    public void setResourceIds( int... resourceIds )
    {
        mResourceIds = resourceIds;
        fillImageViews();
    }

    private void swapImage()
    {
        Log.d( TAG, "swapImage active=" + mActiveImageIndex );
        if( android.os.Build.VERSION.SDK_INT < 11 )
        {
            return;
        }

        if( mActiveImageIndex == -1 )
        {
            mActiveImageIndex = 1;
            animate( mImageViews[mActiveImageIndex] );
            return;
        }

        int inactiveIndex = mActiveImageIndex;
        mActiveImageIndex = ( 1 + mActiveImageIndex ) % mImageViews.length;
        Log.d( TAG, "new active=" + mActiveImageIndex );

        final ImageView activeImageView = mImageViews[mActiveImageIndex];
        activeImageView.setAlpha( 0.0f );
        ImageView inactiveImageView = mImageViews[inactiveIndex];

        animate( activeImageView );

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration( mFadeInOutMs );
        animatorSet.playTogether( ObjectAnimator.ofFloat( inactiveImageView, "alpha", 1.0f, 0.0f ), ObjectAnimator.ofFloat( activeImageView, "alpha", 0.0f, 1.0f ) );
        animatorSet.start();
    }

    private void start( View view, long duration, float fromScale, float toScale, float fromTranslationX, float fromTranslationY, float toTranslationX, float toTranslationY )
    {
        if( android.os.Build.VERSION.SDK_INT < 11 )
        {
            return;
        }

        view.setScaleX( fromScale );
        view.setScaleY( fromScale );
        view.setTranslationX( fromTranslationX );
        view.setTranslationY( fromTranslationY );
        ViewPropertyAnimator propertyAnimator = view.animate().translationX( toTranslationX ).translationY( toTranslationY ).scaleX( toScale ).scaleY( toScale ).setDuration( duration );
        propertyAnimator.start();
        Log.d( TAG, "starting Ken Burns animation " + propertyAnimator );
    }

    private float pickScale()
    {
        return this.minScaleFactor + this.random.nextFloat() * ( this.maxScaleFactor - this.minScaleFactor );
    }

    private float pickTranslation( int value, float ratio )
    {
        return value * ( ratio - 1.0f ) * ( this.random.nextFloat() - 0.5f );
    }

    public void animate( View view )
    {
        float fromScale = pickScale();
        float toScale = pickScale();
        float fromTranslationX = pickTranslation( view.getWidth(), fromScale );
        float fromTranslationY = pickTranslation( view.getHeight(), fromScale );
        float toTranslationX = pickTranslation( view.getWidth(), toScale );
        float toTranslationY = pickTranslation( view.getHeight(), toScale );
        start( view, this.mSwapMs, fromScale, toScale, fromTranslationX, fromTranslationY, toTranslationX, toTranslationY );
    }

    @Override
    protected void onAttachedToWindow()
    {
        super.onAttachedToWindow();
        startKenBurnsAnimation();
    }

    @Override
    protected void onDetachedFromWindow()
    {
        super.onDetachedFromWindow();
        mHandler.removeCallbacks( mSwapImageRunnable );
    }

    private void startKenBurnsAnimation()
    {
        mHandler.post( mSwapImageRunnable );
    }

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();
        View view = inflate( getContext(), R.layout.view_kenburns, this );

        mImageViews = new ImageView[2];
        mImageViews[0] = (ImageView)view.findViewById( R.id.image0 );
        mImageViews[1] = (ImageView)view.findViewById( R.id.image1 );
    }

    private void fillImageViews()
    {
        for( int i = 0; i < mImageViews.length; i++ )
        {
            mImageViews[i].setImageResource( mResourceIds[i] );
        }
    }
}